﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace _1.ComplexNumbers.Model
{
    public class ComplexNumber
    {
        // immutable

        private double real;
        private double imaginary;

        public double Real
        {
            get { return this.real; }
        }

        public double Imaginary
        {
            get { return this.imaginary; }
        }

        public ComplexNumber(double real, double imaginary)
        {
            this.real = real;
            this.imaginary = imaginary;
        }

        public ComplexNumber()
            :this(0, 0)
        {            
        }

        public ComplexNumber(ComplexNumber other)
        {
            this.real = other.real;
            this.imaginary = other.imaginary;
        }

        public double this[int index]
        { 
            get
            {
                if (index == 0)
                {
                    return this.Real;
                }

                if (index == 1)
                {
                    return this.Imaginary;
                }

                throw new ArgumentOutOfRangeException("Index must be 0 or 1.");
            }
        }

        public static ComplexNumber operator +(ComplexNumber x, ComplexNumber y)
        {
            double real = x.real + y.real;
            double imaginary = x.imaginary + y.imaginary;
            ComplexNumber newComplexNumber = new ComplexNumber(real, imaginary);
            return newComplexNumber;
        }

        public static ComplexNumber operator -(ComplexNumber x, ComplexNumber y)
        {
            double real = x.real - y.real;
            double imaginary = x.imaginary - y.imaginary;
            ComplexNumber newComplexNumber = new ComplexNumber(real, imaginary);
            return newComplexNumber;
        }

        public static ComplexNumber operator *(ComplexNumber x, ComplexNumber y)
        {
            double real = x.real * y.real - x.imaginary * y.imaginary;
            double imaginary = x.real * y.imaginary + x.imaginary * y.real;
            ComplexNumber newComplexNumber = new ComplexNumber(real, imaginary);
            return newComplexNumber;
        }

        public static implicit operator ComplexNumber(double d)
        {
            return new ComplexNumber(d, 0);
        }

        public static explicit operator double(ComplexNumber complexNumber)
        {
            return complexNumber.Real;
        }

        public override string ToString()
        {
            string stringedComplexNumber = "0";

            if (this.real != 0 && this.imaginary == 0)
            {
                stringedComplexNumber = this.real.ToString();
            }
            else if (this.real == 0 && this.imaginary != 0)
            {
                stringedComplexNumber = this.imaginary.ToString() + "i";                
            }
            else if (this.real != 0 && this.imaginary != 0)
            {
                double positiveImaginary = Math.Abs(this.imaginary);

                string sign = this.imaginary > 0 ? " + " : " - ";

                stringedComplexNumber = this.real + sign + positiveImaginary + "i";
            }

            return stringedComplexNumber;
        }
    }
}
